package com.yx.test3d.map;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.SparseArray;

import com.yx.test3d.R;
import com.yx.test3d.RectangleArea;
import com.yx.test3d.bean.Area3D;
import com.yx.test3d.bean.ModelData;
import com.yx.test3d.bean.MtlInfo;
import com.yx.test3d.bean.Obj3D;
import com.yx.test3d.bean.Path3D;
import com.yx.test3d.model.Model;
import com.yx.test3d.model.ObjModel;
import com.yx.test3d.utils.LogUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

public class MapDataConverter {
    //原始立方体顶点坐标
    static float[] originCubeVertex = new float[]{
            -0.5f, 0.5f, 0.5f,//前 左 上
            0.5f, 0.5f, 0.5f,//前 右 上
            0.5f, -0.5f, 0.5f,//前 右 下
            -0.5f, -0.5f, 0.5f,//前 左 下
            -0.5f, 0.5f, -0.5f,//后 左 上
            0.5f, 0.5f, -0.5f,//后 右 上
            0.5f, -0.5f, -0.5f,//后 右 下
            -0.5f, -0.5f, -0.5f,//后 左 下
    };
    //每块地板立方体顶点坐标  需要根据位置来计算
    static float[] currentCubeVertex = new float[24];
    //法线坐标
    static float[] originCubeNormal = new float[]{
            0, 1, 0,//上
            0, -1, 0,//下
            -1, 0, 0,//左
            1, 0, 0,//右
            0, 0, 1,//前
            0, 0, -1//后
    };
    //纹理坐标
    static float[] currentCubeTexture = new float[8];
    static float[] currentFloorDownTexture = new float[8];
    static float[] currentWallBackTexture = new float[8];
    static float[] currentWallFrontTexture = new float[8];
    static float[] currentWallLeftTexture = new float[8];
    static float[] currentWallRightTexture = new float[8];
    static float[] originCubeTextureCoordinate = new float[]{
            0.0f, 0.0f,
            0.0f, 1.0f,
            1.0f, 1.0f,
            1.0f, 0.0f,
    };
    //绘制一个立方体的36个顶点的索引
    static int[] vertexIndex = new int[]{
            3, 1, 0, 3, 2, 1,//正面两个三角形
            6, 4, 5, 6, 7, 4,//背面
            7, 0, 4, 7, 3, 0,//左侧
            2, 5, 1, 2, 6, 5, //右侧
            0, 5, 4, 0, 1, 5, //上
            7, 2, 3, 7, 6, 2
    };
    //立方体的36个顶点法向量的索引
    static int[] normalIndex = new int[]{
            4, 4, 4, 4, 4, 4,//正面两个三角形
            5, 5, 5, 5, 5, 5,//背面
            2, 2, 2, 2, 2, 2,//左侧
            3, 3, 3, 3, 3, 3, //右侧
            0, 0, 0, 0, 0, 0,//上
            1, 1, 1, 1, 1, 1//下
    };
    //立方体的36个顶点纹理的索引
    static int[] textureIndex = new int[]{
            1, 3, 0, 1, 2, 3,//正面两个三角形
            1, 3, 0, 1, 2, 3,//背面
            1, 3, 0, 1, 2, 3,//左侧
            1, 3, 0, 1, 2, 3, //右侧
            1, 3, 0, 1, 2, 3, //上
            1, 3, 0, 1, 2, 3//下
    };
    private static float UNIT_SIZE = 0.1f;  //表示每个格子的大小  后面取值会设置成 resolution*2    默认应该是0.1

    //数据转换成obj格式
    public static List<Obj3D> mapDataToObj(Context context, int width, int height, int[] data, float resolution) {
        int floorFaceCount = 0;
        int wallFaceCount = 0;
        SparseArray<boolean[]> floorFaces = new SparseArray<>();
        SparseArray<boolean[]> wallFaces = new SparseArray<>();
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int type = data[i * width + j];
                //计算立方体6个面有无相邻
                if (type == 0) {
                    //0 墙内
                    boolean[] adjucent = new boolean[]{false, false, false, false, false, false};
                    int faceCount = isAdjucency(data, width, height, i, j, adjucent);
                    floorFaceCount += faceCount;
                    floorFaces.put(i * width + j, adjucent);
                } else if (type == 1) {
                    //1 墙
                    boolean[] adjucent = new boolean[]{false, false, false, false, false, false};
                    int faceCount = isWallAdjucency(data, width, height, i, j, adjucent);
                    wallFaceCount += faceCount;
                    wallFaces.put(i * width + j, adjucent);
                } else if (type == 2) {
                    //2 墙外
                } else {

                }
            }
        }
        //UNIT_SIZE 现在默认是resolution * 2  resolution默认为0.05  也就是地板方块长宽高0.1m
        UNIT_SIZE = resolution * 2;

        List<Obj3D> obj3Ds = new ArrayList<>();
        Obj3D floor = genFloorObj(context, width, height, data, floorFaces, floorFaceCount);
        obj3Ds.add(floor);


        Obj3D wall = genWallObj(context, width, height, data, wallFaces, wallFaceCount);
        obj3Ds.add(wall);
        return obj3Ds;
    }

    public static Area3D areaToObj(Context context, int width, int height, float resolution, RectangleArea rectangleArea) {
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.forbid_area);
        float wallHeight = resolution * 20;
        float wallTileSize = 1f;
        float wallTileUnit = resolution;  //地图每一格栅格 在现实中为0.05  在opengl中也是0.05
        float wallTextureUnit = resolution / wallTileSize;

        FloatBuffer vertex = ByteBuffer.allocateDirect(4 * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer vertexTexture = ByteBuffer.allocateDirect(4 * 2 * 3 * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

        float offsetX = -(rectangleArea.lt.x+rectangleArea.rb.x)/ 2  * wallTileUnit;
        float offsetY = -wallTileUnit / 2;
        float offsetZ = -(rectangleArea.lt.y+rectangleArea.rb.y)/ 2 * wallTileUnit;

        //虚拟墙上下两个面不画
        boolean[] adjust = new boolean[]{false, false, false, false, true, true};
        addAreaCuboidVertex(vertex, vertexTexture,
                rectangleArea.width , wallHeight, rectangleArea.height,
                rectangleArea.width/wallTileUnit ,  20, rectangleArea.height/wallTileUnit,
                offsetX, offsetY, offsetZ,
                adjust);
        vertex.flip();
        vertexTexture.flip();
        LogUtils.i(vertex.toString());
        LogUtils.i(vertexTexture.toString());
        Area3D area3D= Area3D.newBuilder().bitmap(bitmap).vertex(vertex).texture(vertexTexture).build();

        return area3D;
    }

    /**
     * 从地图上的xy 转换成3d的偏移 x z
     * @param offset
     */
    public static float convertOffset(float offset) {
        return offset * UNIT_SIZE;
    }

    /**
     * 生成地板的Obj3D 对象
     * @param width 地图宽
     * @param height   地图高
     * @param data  地图数据
     * @param faces 需要绘制的面
     * @param faceCount 绘制面的个数
     * @return Obj3D
     */
    public static Obj3D genFloorObj(Context context, int width, int height, int[] data, SparseArray<boolean[]> faces, int faceCount) {

        //        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.woodfloor);
        //        Bitmap normalBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.woodfloor_normal);

        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.brickwall);
        Bitmap normalBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.brickwall_normal);
        //        Bitmap normalBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.brickwall_normal_flip);
        MtlInfo mtlInfo = MtlInfo.newBuilder()
                .Ka(new float[]{1, 1, 1})
                .Kd(new float[]{245 / 255f, 245 / 255f, 245 / 255f})
                .Ks(new float[]{18 / 255f, 18 / 255f, 18 / 255f})
                .Ke(new float[]{1f, 1f, 1f})
                .kd(bitmap)
                .kdNormal(normalBitmap)
                .Ns(1)
                .illum(7)
                .build();

        //Buffer大小等于: 面数* 每个面2个三角形* 每个三角形3个顶点* 每个顶点3个维度(xyz) * 每个维度四字节(float) : faceCount* 2*3*3*4
        FloatBuffer vertex = ByteBuffer.allocateDirect(faceCount * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer vertexNormal = ByteBuffer.allocateDirect(faceCount * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer vertexTexture = ByteBuffer.allocateDirect(faceCount * 2 * 3 * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

        genFloorVetextData(vertex, vertexTexture, vertexNormal, data, width, height, faces);

        Obj3D obj3D = Obj3D.newBuilder()
                .mtl(mtlInfo)
                .position(vertex)
                .normal(vertexNormal)
                .texture(vertexTexture)
                .vertCount(vertex.limit() / 3)
                .build();
        return obj3D;
    }

    /**
     * 生成墙的Obj3D 对象
     * @param width 地图宽
     * @param height   地图高
     * @param data  地图数据
     * @param faces 需要绘制的面
     * @param faceCount 绘制面的个数
     * @return Obj3D
     * 当前墙和地板只有高度不同,  后期可能会有其他变化
     */
    public static Obj3D genWallObj(Context context, int width, int height, int[] data, SparseArray<boolean[]> faces, int faceCount) {
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.wall_plmm);
        MtlInfo mtlInfo = MtlInfo.newBuilder()
                .Ka(new float[]{0, 0, 0})
                .Kd(new float[]{239 / 255f, 178 / 255f, 129 / 255f})
                .Ks(new float[]{20 / 255f, 20 / 255f, 20 / 255f})
                .Ke(new float[]{1f, 1f, 1f})
                .kd(bitmap)
                .Ns(1)
                .illum(7)
                .build();
        FloatBuffer vertex = ByteBuffer.allocateDirect(faceCount * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer vertexNormal = ByteBuffer.allocateDirect(faceCount * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer vertexTexture = ByteBuffer.allocateDirect(faceCount * 2 * 3 * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

        genWallVetexData(vertex, vertexTexture, vertexNormal, data, width, height, faces);
        LogUtils.i("wall vertex size : " + vertex.toString());

        LogUtils.i(vertex.toString());
        Obj3D obj3D = Obj3D.newBuilder()
                .mtl(mtlInfo)
                .position(vertex)
                .normal(vertexNormal)
                .texture(vertexTexture)
                .vertCount(vertex.limit() / 3)
                .build();
        return obj3D;
    }

    /**
     * 把顶点数据添加到Buffer中
     */
    public static void genFloorVetextData(FloatBuffer vertex, FloatBuffer vertexTexture, FloatBuffer vertexNormal, int[] data, int width, int height, SparseArray<boolean[]> faces) {
        float floorTileSize = 2f;
        float resolution = 0.05f;
        float floorTileUnit = resolution;
        float floorTileTextureUnit = resolution / floorTileSize;

        float offsetX = -width / 2 * floorTileUnit;
        float offsetY = -floorTileUnit / 2;
        float offsetZ = -height / 2 * floorTileUnit;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int type = data[i * width + j];
                if (type == 0) {
                    //0 墙内
                    boolean[] adjucent = faces.get(i * width + j);
                    addfloorCuboidVertex(vertex, vertexTexture, vertexNormal,
                            floorTileUnit, floorTileUnit, floorTileUnit,
                            floorTileTextureUnit, floorTileTextureUnit, floorTileTextureUnit, //纹理大小,  一格是0.05 代表现实的5厘米, 20格就是纹理坐标的1 , 地砖如果是0.8, 那么16格就是一块地砖  1格就是1/16
                            j, 0, i,
                            offsetX, offsetY, offsetZ,
                            adjucent);
                }
            }
        }
        //genFloor(vertex, vertexTexture, vertexNormal, width, height, resolution); //直接画宽高大小的地板

        vertex.flip();
        vertexNormal.flip();
        vertexTexture.flip();


    }

    public static void genWallVetexData(FloatBuffer vertex, FloatBuffer vertexTexture, FloatBuffer vertexNormal, int[] data, int width, int height, SparseArray<boolean[]> faces) {
        float wallTileSize = 0.78f;
        float resolution = 0.05f;
        float wallTileUnit = resolution;
        float wallTextureUnit = resolution / wallTileSize;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int type = data[i * width + j];
                //计算立方体6个面有无相邻
                if (type == 1) {
                    //1 墙
                    boolean[] adjucent = faces.get(i * width + j);

                    float offsetX = -width / 2 * wallTileUnit;
                    float offsetY = -wallTileUnit / 2;
                    float offsetZ = -height / 2 * wallTileUnit;

                    addWallCuboidVertex(vertex, vertexTexture, vertexNormal,
                            wallTileUnit, wallTileUnit * 20, wallTileUnit,
                            wallTextureUnit, wallTextureUnit * 20, wallTextureUnit, //纹理大小,  一格是0.05 代表现实的5厘米, 20格就是纹理坐标的1 , 地砖如果是0.8, 那么16格就是一块地砖  1格就是1/16
                            j, 0, i,
                            offsetX, offsetY, offsetZ,
                            adjucent);
                }
            }
        }
        vertex.flip();
        vertexNormal.flip();
        vertexTexture.flip();
    }

    public static Model genShadowTestCubeAndFloor(Context context) {
        boolean[] adjucent = new boolean[]{false, false, false, false, false, false};
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.floor);
        MtlInfo mtlInfo = MtlInfo.newBuilder()
                .Ka(new float[]{1, 1, 1})
                .Kd(new float[]{128 / 255f, 128 / 255f, 245 / 255f})
                .Ks(new float[]{18 / 255f, 18 / 255f, 18 / 255f})
                .Ns(10)
                .kd(bitmap)
                .build();
        FloatBuffer vertex = ByteBuffer.allocateDirect(6 * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer vertexNormal = ByteBuffer.allocateDirect(6 * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer vertexTexture = ByteBuffer.allocateDirect(6 * 2 * 3 * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

        UNIT_SIZE = 0.5f;
        float rectX = UNIT_SIZE;
        float rectY = UNIT_SIZE;
        float rectZ = UNIT_SIZE;

        float floorTileSize = 1f;
        float resolution = 1f;
        float floorTileTextureUnit = resolution / floorTileSize;
        addfloorCuboidVertex(vertex, vertexTexture, vertexNormal,
                rectX, rectY, rectZ,
                floorTileTextureUnit, floorTileTextureUnit, floorTileTextureUnit, //纹理大小,  一格是0.05 代表现实的5厘米, 20格就是纹理坐标的1 , 地砖如果是0.8, 那么16格就是一块地砖  1格就是1/16
                0, 1, 0,
                0, 0, 0,
                adjucent);


        vertex.flip();
        vertexNormal.flip();
        vertexTexture.flip();
        Obj3D cubeData = Obj3D.newBuilder().position(vertex).normal(vertexNormal).texture(vertexTexture).mtl(mtlInfo).build();


        mtlInfo = MtlInfo.newBuilder()
                .Ka(new float[]{1, 1, 1})
                .Kd(new float[]{1, 1, 1})
                .Ks(new float[]{1, 1, 1})
                .Ns(10)
                .kd(bitmap)
                .build();
        vertex = ByteBuffer.allocateDirect(6 * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vertexNormal = ByteBuffer.allocateDirect(6 * 2 * 3 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vertexTexture = ByteBuffer.allocateDirect(6 * 2 * 3 * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        rectX = UNIT_SIZE * 8;
        rectY = UNIT_SIZE / 2;
        rectZ = UNIT_SIZE * 8;
        //        addCuboidVertex(vertex, vertexTexture, vertexNormal,
        //                rectX / 2, rectY / 2, rectZ / 2,
        //                0, -UNIT_SIZE / 2 - 0.2f, 0,
        //                adjucent);
        addfloorCuboidVertex(vertex, vertexTexture, vertexNormal,
                rectX, rectY, rectZ,
                floorTileTextureUnit, floorTileTextureUnit, floorTileTextureUnit, //纹理大小,  一格是0.05 代表现实的5厘米, 20格就是纹理坐标的1 , 地砖如果是0.8, 那么16格就是一块地砖  1格就是1/16
                0, 0, 0,
                0, 0, 0,
                adjucent);

        vertex.flip();
        vertexNormal.flip();
        vertexTexture.flip();
        Obj3D floorData = Obj3D.newBuilder().position(vertex).normal(vertexNormal).texture(vertexTexture).mtl(mtlInfo).build();

        List<Obj3D> objectDataList = new ArrayList<>();
        objectDataList.add(cubeData);
        objectDataList.add(floorData);

        return new ObjModel(objectDataList);
        //                 return new TestFboModel(objectDataList);
        //                 return new TestModel(objectDataList);

    }

    /**
     * 计算每个方块有无相邻,并计算需要绘制少个面
     * 相邻的结果存在boolean数组中  顺序为: 前 后 左 右 上 下
     * 有相邻 为true  不用画这个面
     * 无相邻 为false
     */
    public static int isAdjucency(int[] mapData, int w, int h, int i, int j, boolean[] adjucent) {

        int faceCount = 6; //总共6个面

        int positionFront = (i + 1) * w + j;
        int positiBack = (i - 1) * w + j;
        int positionLeft = i * w + j - 1;
        int positionRight = i * w + j + 1;
        //前面有格子
        if (i + 1 < h && mapData[positionFront] < 2) {
            adjucent[0] = true;
            faceCount--; //有相邻的面不画
        }

        //后面有格子
        if (i - 1 >= 0 && mapData[positiBack] < 2) {
            adjucent[1] = true;
            faceCount--;
        }

        //左面有格子
        if (j - 1 >= 0 && mapData[positionLeft] < 2) {
            adjucent[2] = true;
            faceCount--;
        }

        //右面有格子
        if (j + 1 < w && mapData[positionRight] < 2) {
            adjucent[3] = true;
            faceCount--;
        }

        //上下两个面暂时都画
        adjucent[4] = false;
        adjucent[5] = false;
        return faceCount;
    }

    /**
     * 判断墙方块是否相邻墙方块 并计算需要绘制少个面
     * 两面墙相邻才可以不绘制共有的那面墙
     * @return
     */
    public static int isWallAdjucency(int[] mapData, int w, int h, int i, int j, boolean[] adjucent) {

        int faceCount = 6;

        int positionFront = (i + 1) * w + j;
        int positiBack = (i - 1) * w + j;
        int positionLeft = i * w + j - 1;
        int positionRight = i * w + j + 1;
        //前面有格子
        if (i + 1 < h && mapData[positionFront] == 1) {
            adjucent[0] = true;
            faceCount--;
        }

        //后面有格子
        if (i - 1 >= 0 && mapData[positiBack] == 1) {
            adjucent[1] = true;
            faceCount--;
        }

        //左面有格子
        if (j - 1 >= 0 && mapData[positionLeft] == 1) {
            adjucent[2] = true;
            faceCount--;
        }

        //右面有格子
        if (j + 1 < w && mapData[positionRight] == 1) {
            adjucent[3] = true;
            faceCount--;
        }

        //上下两个面暂时都画
        adjucent[4] = false;
        adjucent[5] = false;
        return faceCount;
    }

    public static void addfloorCuboidVertex(FloatBuffer v, FloatBuffer vt, FloatBuffer vn,
                                            float rectX, float rectY, float rectZ,
                                            float textureX, float textureY, float textureZ,
                                            float positionX, float positionY, float positionZ,
                                            float offsetX, float offsetY, float offsetZ,
                                            boolean[] adjucent) {
        //每个矩形根据位置不同 重新设置长宽高和偏移
        for (int i = 0; i < currentCubeVertex.length; i++) {
            if (i % 3 == 0) {
                currentCubeVertex[i] = (originCubeVertex[i] + positionX) * rectX + offsetX;
            } else if (i % 3 == 1) {
                currentCubeVertex[i] = (originCubeVertex[i] + positionY) * rectY + offsetY;
            } else if (i % 3 == 2) {
                currentCubeVertex[i] = (originCubeVertex[i] + positionZ) * rectZ + offsetZ;
            }
        }

        for (int i = 0; i < originCubeTextureCoordinate.length; i++) {
            if (i % 2 == 0) {
                currentCubeTexture[i] = (originCubeTextureCoordinate[i] + positionX) * textureX;

                currentFloorDownTexture[i] = (originCubeTextureCoordinate[i] + positionX) * textureX;
            } else if (i % 2 == 1) {
                currentCubeTexture[i] = (originCubeTextureCoordinate[i] + positionZ) * textureZ;

                currentFloorDownTexture[i] = (originCubeTextureCoordinate[i] - positionZ) * textureZ;
            }
        }


        for (int i = 0; i < adjucent.length; i++) {
            //根据adjucent 判断需要添加几个面 有相邻的面不用添加
            //每个面六个点 每个点有 坐标xyz 法向量xyz 纹理坐标xy
            if (!adjucent[i]) {
                for (int j = 0; j < 6; j++) {
                    int k = i * 6 + j;
                    v.put(currentCubeVertex[vertexIndex[k] * 3]);
                    v.put(currentCubeVertex[vertexIndex[k] * 3 + 1]);
                    v.put(currentCubeVertex[vertexIndex[k] * 3 + 2]);

                    vn.put(originCubeNormal[normalIndex[k] * 3]);
                    vn.put(originCubeNormal[normalIndex[k] * 3 + 1]);
                    vn.put(originCubeNormal[normalIndex[k] * 3 + 2]);

                    //                    vt.put(originCubeTextureCoordinate[textureIndex[k] * 2]);
                    //                    vt.put(originCubeTextureCoordinate[textureIndex[k] * 2 + 1]);

                    if (i == 4) {
                        vt.put(currentCubeTexture[textureIndex[k] * 2]);
                        vt.put(currentCubeTexture[textureIndex[k] * 2 + 1]);
                    } else if (i == 5) {
                        vt.put(currentFloorDownTexture[textureIndex[k] * 2]);
                        vt.put(currentFloorDownTexture[textureIndex[k] * 2 + 1]);
                    } else {
                        vt.put(0.5f);
                        vt.put(0.5f);
                    }
                }
            }

        }
    }

    public static void addAreaCuboidVertex(FloatBuffer v, FloatBuffer vt,
                                           float rectX, float rectY, float rectZ,
                                           float textureX, float textureY, float textureZ,
                                           float offsetX, float offsetY, float offsetZ,
                                           boolean[] adjucent) {
        //每个矩形根据位置不同 重新设置长宽高和偏移
        for (int i = 0; i < currentCubeVertex.length; i++) {
            if (i % 3 == 0) {
                currentCubeVertex[i] = (originCubeVertex[i]) * rectX + offsetX;
            } else if (i % 3 == 1) {
                currentCubeVertex[i] = (originCubeVertex[i]) * rectY + offsetY;
            } else if (i % 3 == 2) {
                currentCubeVertex[i] = (originCubeVertex[i]) * rectZ + offsetZ;
            }
        }


        for (int i = 0; i < originCubeTextureCoordinate.length; i++) {
            if (i % 2 == 0) {
                currentWallFrontTexture[i] = (originCubeTextureCoordinate[i] ) * textureX;
                currentWallBackTexture[i] = (originCubeTextureCoordinate[i] ) * textureX;

                currentWallLeftTexture[i] = (originCubeTextureCoordinate[i] ) * textureZ;
                currentWallRightTexture[i] = (originCubeTextureCoordinate[i] ) * textureZ;
            } else if (i % 2 == 1) {
                currentWallFrontTexture[i] = originCubeTextureCoordinate[i] * textureY;
                currentWallBackTexture[i] = originCubeTextureCoordinate[i] * textureY;

                currentWallLeftTexture[i] = originCubeTextureCoordinate[i] * textureY;
                currentWallRightTexture[i] = originCubeTextureCoordinate[i] * textureY;
            }
        }


        for (int i = 0; i < adjucent.length; i++) {
            //根据adjucent 判断需要添加几个面 有相邻的面不用添加
            //每个面六个点 每个点有 坐标xyz 法向量xyz 纹理坐标xy
            if (!adjucent[i]) {
                for (int j = 0; j < 6; j++) {
                    int k = i * 6 + j;
                    v.put(currentCubeVertex[vertexIndex[k] * 3]);
                    v.put(currentCubeVertex[vertexIndex[k] * 3 + 1]);
                    v.put(currentCubeVertex[vertexIndex[k] * 3 + 2]);

                    if (i == 0) {
                        vt.put(currentWallFrontTexture[textureIndex[k] * 2]);
                        vt.put(currentWallFrontTexture[textureIndex[k] * 2 + 1]);
                    } else if (i == 1) {
                        vt.put(currentWallBackTexture[textureIndex[k] * 2]);
                        vt.put(currentWallBackTexture[textureIndex[k] * 2 + 1]);
                    } else if (i == 2) {
                        vt.put(currentWallLeftTexture[textureIndex[k] * 2]);
                        vt.put(currentWallLeftTexture[textureIndex[k] * 2 + 1]);
                    } else if (i == 3) {
                        vt.put(currentWallRightTexture[textureIndex[k] * 2]);
                        vt.put(currentWallRightTexture[textureIndex[k] * 2 + 1]);
                    } else {
                        //没有上下两个面
                        vt.put(0.5f);
                        vt.put(0.5f);
                    }


                }
            }

        }
    }

    public static void addWallCuboidVertex(FloatBuffer v, FloatBuffer vt, FloatBuffer vn,
                                           float rectX, float rectY, float rectZ,
                                           float textureX, float textureY, float textureZ,
                                           float positionX, float positionY, float positionZ,
                                           float offsetX, float offsetY, float offsetZ,

                                           boolean[] adjucent) {
        //每个矩形根据位置不同 重新设置长宽高和偏移
        for (int i = 0; i < currentCubeVertex.length; i++) {
            if (i % 3 == 0) {
                currentCubeVertex[i] = (originCubeVertex[i] + positionX) * rectX + offsetX;
            } else if (i % 3 == 1) {
                currentCubeVertex[i] = (originCubeVertex[i] + positionY) * rectY + offsetY;
            } else if (i % 3 == 2) {
                currentCubeVertex[i] = (originCubeVertex[i] + positionZ) * rectZ + offsetZ;
            }
        }


        for (int i = 0; i < originCubeTextureCoordinate.length; i++) {
            if (i % 2 == 0) {
                currentWallFrontTexture[i] = (originCubeTextureCoordinate[i] + positionX) * textureX;
                currentWallBackTexture[i] = (originCubeTextureCoordinate[i] - positionX) * textureX;

                currentWallLeftTexture[i] = (originCubeTextureCoordinate[i] + positionZ) * textureZ;
                currentWallRightTexture[i] = (originCubeTextureCoordinate[i] - positionZ) * textureZ;
            } else if (i % 2 == 1) {
                currentWallFrontTexture[i] = originCubeTextureCoordinate[i] * textureY;
                currentWallBackTexture[i] = originCubeTextureCoordinate[i] * textureY;

                currentWallLeftTexture[i] = originCubeTextureCoordinate[i] * textureY;
                currentWallRightTexture[i] = originCubeTextureCoordinate[i] * textureY;
            }
        }


        for (int i = 0; i < adjucent.length; i++) {
            //根据adjucent 判断需要添加几个面 有相邻的面不用添加
            //每个面六个点 每个点有 坐标xyz 法向量xyz 纹理坐标xy
            if (!adjucent[i]) {
                for (int j = 0; j < 6; j++) {
                    int k = i * 6 + j;
                    v.put(currentCubeVertex[vertexIndex[k] * 3]);
                    v.put(currentCubeVertex[vertexIndex[k] * 3 + 1]);
                    v.put(currentCubeVertex[vertexIndex[k] * 3 + 2]);

                    vn.put(originCubeNormal[normalIndex[k] * 3]);
                    vn.put(originCubeNormal[normalIndex[k] * 3 + 1]);
                    vn.put(originCubeNormal[normalIndex[k] * 3 + 2]);

                    //                    vt.put(originCubeTextureCoordinate[textureIndex[k] * 2]);
                    //                    vt.put(originCubeTextureCoordinate[textureIndex[k] * 2 + 1]);

                    if (i == 0) {
                        vt.put(currentWallFrontTexture[textureIndex[k] * 2]);
                        vt.put(currentWallFrontTexture[textureIndex[k] * 2 + 1]);
                    } else if (i == 1) {
                        vt.put(currentWallBackTexture[textureIndex[k] * 2]);
                        vt.put(currentWallBackTexture[textureIndex[k] * 2 + 1]);
                    } else if (i == 2) {
                        vt.put(currentWallLeftTexture[textureIndex[k] * 2]);
                        vt.put(currentWallLeftTexture[textureIndex[k] * 2 + 1]);
                    } else if (i == 3) {
                        vt.put(currentWallRightTexture[textureIndex[k] * 2]);
                        vt.put(currentWallRightTexture[textureIndex[k] * 2 + 1]);
                    } else {
                        //上下两个面
                        vt.put(0.5f);
                        vt.put(0.5f);
                    }


                }
            }

        }
    }

    /**
     *  生成路径的数据
     * @param width
     * @param height
     * @param resolution
     * @param x_min 路径相对于地图的偏移x
     * @param y_min 路径相对于地图的偏移y
     * @param path
     * @return
     */
    public static Path3D convertPathData(float width, float height, float resolution, float x_min, float y_min, List<Integer> path) {

        //buffer大小 = 路径点的xy个数 +  一个z轴坐标( *3/2 ) * 每个维度字节数 (float 4)
        FloatBuffer vertex = ByteBuffer.allocateDirect(path.size() / 2 * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        UNIT_SIZE = resolution * 2;

        for (int i = 0; i < path.size() / 2; i++) {
            float x = width - (path.get(i * 2 + 1) / 5 - y_min * 20); //计算方式就是这样 别问为什么
            float z = height - (path.get(i * 2) / 5 - x_min * 20);

            x = x * UNIT_SIZE - width * UNIT_SIZE / 2;         //将地图制定点 缩放平移到3d地图的指定位置
            z = z * UNIT_SIZE - height * UNIT_SIZE / 2;

            float y = UNIT_SIZE * 3 / 2;
            vertex.put(x);
            vertex.put(y);
            vertex.put(z);
        }
        vertex.flip();

        Path3D path3D = Path3D.newBuilder().color(new float[]{0, 0, 1}).vert(vertex).build();

        return path3D;
    }

    /**
     *  计算模型缩放倍数
     * @param realSize  模型真实大小  单位 m
     * @param modelScale   模型取值范围
     * @return
     */
    public static float calculateModelScale(float realSize, float modelScale) {
        return realSize / modelScale;
    }

    /**
     * 只用一个长方体绘制地面, 不考虑清扫
     */
    public void genFloor(FloatBuffer v, FloatBuffer vt, FloatBuffer vn, int width, int height) {
        float rectX = width * UNIT_SIZE;
        float rectY = UNIT_SIZE;
        float rectZ = height * UNIT_SIZE;

        float offsetX = -width * UNIT_SIZE / 2;
        float offsetY = UNIT_SIZE / 2;
        float offsetZ = -height * UNIT_SIZE / 2;
        boolean[] adjucent = new boolean[]{false, false, false, false, false, false};
        //        addCuboidVertex(v, vt, vn, rectX, rectY, rectZ, offsetX, offsetY, offsetZ, adjucent);
    }


}
